﻿/*
 * devicestate.hpp
 *
 *  Created on: 2017年9月15日
 *      Author: work
 */

#ifndef _DM_SCADA_DEVICESTATE_HPP_
#define _DM_SCADA_DEVICESTATE_HPP_

#include <dm/export.hpp>

#ifndef DM_API_SCADA
#define DM_API_SCADA DM_API_IMPORT
#endif

#include <dm/types.hpp>
#include <dm/runtimestamp.hpp>
#include <dm/ringpos.hpp>

namespace dm{
namespace scada{

/**
 * 设备状态信息
 */
class DM_API_SCADA CDeviceState{
	CDeviceState( const CDeviceState& );
	CDeviceState& operator=( const CDeviceState& );
public:
	typedef dm::CRingPos<dm::uint32,dm::uint32,0xffffffffu> count_t;

	/**
	 * 设备状态
	 */
	enum EState{
		ESSysInit,		//!< 系统初始化
		ESComConnting,	//!< 通信采集连接中
		ESComConnted,	//!< 通信采集已连接
		ESComFail,		//!< 通信采集连接失败
		ESComDiscon,	//!< 通信采集断开连接
		ESLocalRun,		//!< 本地采集正在运行
		ESLocalStop		//!< 本地采集未运行
	};

	CDeviceState();

	/**
	 * 设备是否有效
	 * @param now
	 * @return
	 */
	inline bool isAlive( const dm::CRunTimeStamp& now=dm::CRunTimeStamp::cur() )const{
		if( m_lastState==ESComConnted )
			return !(m_lastRx.isTimeout_sec(m_stateLifeInSec,now) || m_lastStateTime.isTimeout_sec(m_stateLifeInSec,now));

		if( m_lastState==ESLocalRun )
			return !m_lastStateTime.isTimeout_sec(m_stateLifeInSec,now);
		return false;
	}

	void updateState( const EState& state,const dm::CRunTimeStamp& now=dm::CRunTimeStamp::cur() );

	/**
	 * 获取设备最后的状态
	 * @return
	 */
	inline const EState& getLastState()const{
		return m_lastState;
	}

	/**
	 * 获取设备最后的更新时刻
	 * @return
	 */
	inline const dm::CRunTimeStamp& getLastStateTime()const{
		return m_lastStateTime;
	}

	/**
	 * 设置设备存活期：单位秒
	 * @param sec
	 */
	void setStateLifeInSec( const int& sec );

	/**
	 * 获取设备存活期：单位秒
	 * 设备必须在设备存活期时间内更新，否则认为设备离线
	 * @return
	 */
	inline const int& getStateLifeInSec()const{
		return m_stateLifeInSec;
	}

	void rxRecont( const dm::CRunTimeStamp& n=dm::CRunTimeStamp::cur() );
	void txRecont( const dm::CRunTimeStamp& n=dm::CRunTimeStamp::cur() );

	void rxed( dm::uint32 num,const dm::CRunTimeStamp& n=dm::CRunTimeStamp::cur() );
	void txed( dm::uint32 num,const dm::CRunTimeStamp& n=dm::CRunTimeStamp::cur() );

	/**
	 * 获取接收统计字节数
	 * @return
	 */
	inline const count_t& getRxCnt()const{
		return m_rxCnt;
	}

	inline const dm::CRunTimeStamp& getRxStart()const{
		return m_rxStart;
	}

	inline const dm::CRunTimeStamp& getLastRx()const{
		return m_lastRx;
	}

	inline const count_t& getTxCnt()const{
		return m_txCnt;
	}

	inline const dm::CRunTimeStamp& getTxStart()const{
		return m_txStart;
	}

	inline const dm::CRunTimeStamp& getLastTx()const{
		return m_lastTx;
	}

private:
	EState m_lastState;					//!< 设备最后更新的状态
	dm::CRunTimeStamp m_lastStateTime;		//!< 设备最后更新时刻

	int m_stateLifeInSec;				//!< 设备状态有效期：秒

	count_t m_rxCnt;	//!< 接收计数
	count_t m_txCnt;	//!< 发送计数

	dm::CRunTimeStamp m_rxStart;	//!< 接收开始计数时刻
	dm::CRunTimeStamp m_txStart;	//!< 发送开始计数时刻

	dm::CRunTimeStamp m_lastRx;	//!< 最后接收时刻
	dm::CRunTimeStamp m_lastTx;	//!< 最后发送时刻
};

}
}

#endif /* DM_RUNTIME_INCLUDE_DM_SCADA_DEVICESTATE_HPP_ */
